/*
 * Copyright 2022 The Open Islands Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.openislands.oi.master.scheduler;

import org.openislands.oi.config.MyNodeInfo;
import org.openislands.oi.pojo.dto.CommonResult;
import org.openislands.oi.pojo.dto.NodeDTO;
import org.openislands.oi.pojo.dto.RouteDTO;
import org.openislands.oi.pojo.qo.NodeRouteQO;
import org.openislands.oi.pojo.qo.NodeVerifyQO;
import org.openislands.oi.pojo.vo.NodeVO;
import org.openislands.oi.scheduling.NodeCoordinationProtocol;
import org.openislands.oi.util.ValueCopyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@SuppressWarnings("unused")
public class NodeCoordinator {
    private static final Logger log = LoggerFactory.getLogger(NodeCoordinator.class);

    @Resource(type = MyNodeInfo.class)
    private MyNodeInfo myNodeInfo;

    @Resource
    private NodeCoordinationProtocol nodeCoordinationProtocol;

    public CommonResult<NodeDTO> verifyNode(@NonNull NodeDTO nodeDTO) {
        final NodeVerifyQO verifyQO = ValueCopyUtils.copyProperties(myNodeInfo, new NodeVerifyQO(), (info, qo) -> {
            final NodeRouteQO routeQO = new NodeRouteQO();
            routeQO.setNodeId(info.getNodeId());
            routeQO.setHttpAccess(info.getHttpAccess());
            routeQO.setHttpsAccess(info.getHttpsAccess());
            routeQO.setGrpcAccess(info.getGrpcAccess());
            routeQO.setGrpcsAccess(info.getGrpcsAccess());
            qo.setNodeRouteList(Collections.singletonList(routeQO));
            return qo;
        });

        final CommonResult<NodeVO> commonResult = nodeCoordinationProtocol.verifyNode(nodeDTO.getNodeId(), verifyQO);
        final NodeVO responseData = commonResult.getData();
        if (Objects.nonNull(responseData)) {
            NodeDTO data = ValueCopyUtils.copyProperties(responseData, new NodeDTO(), (rd, d) -> {
                d.setRouteDTOList(rd.getNodeRouteList()
                        .stream()
                        .map(ovo -> ValueCopyUtils.copyProperties(ovo, new RouteDTO()))
                        .collect(Collectors.toList())
                );
                return d;
            });
            return new CommonResult<>(commonResult.getCode(), commonResult.getMessage(), data);
        }
        return new CommonResult<>(commonResult.getCode(), commonResult.getMessage());
    }

    public CommonResult<Boolean> pingNode(@NonNull NodeDTO nodeDTO) {
        return nodeCoordinationProtocol.pingNode(nodeDTO.getNodeId());
    }

    public CommonResult<Boolean> breakNode(@NonNull NodeDTO nodeDTO) {
        return nodeCoordinationProtocol.breakNode(nodeDTO.getNodeId(), myNodeInfo.getNodeId());
    }
}
